
package com.example.filetransfer.publicsource.connection;

import com.example.filetransfer.publicsource.Log;
import com.example.filetransfer.publicsource.fileutils.DirUtils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public class DataReceiver extends Thread {
    private static final String TAG = "DataReceiver";
    private FileTransferListener mFileTransferListener;
    // Set the default path as current directory.
    private String mRootPath = ".";
    private InputStream mInputStream;
    private volatile onReceiveMessageListener mMessageListener;
    private OnSocketError mSocketErrorListener = null;
    private static final int RECEIVE_FILE_BUFFERE_SIZE = 1024;

    public interface OnReceiveEndListener {
        public void onFileReceiveFinish();
    }

    public interface onReceiveMessageListener {
        public void receiveMessage(String message);
    }

    public DataReceiver() {
    }

    public DataReceiver(InputStream inputStream) {
        this.mInputStream = inputStream;
    }

    public void setSocketErrorListener(OnSocketError socketError) {
        this.mSocketErrorListener = socketError;
    }

    public void setFileTransferListener(FileTransferListener listener) {
        this.mFileTransferListener = listener;
    }

    public void setMessageListener(onReceiveMessageListener listener) {
        this.mMessageListener = listener;
    }

    public void setInputStream(InputStream inputStream) {
        this.mInputStream = inputStream;
    }

    public void setRootDir(String rootDir) {
        mRootPath = rootDir;
        checkAndCreateRootDir();
    }

    private void checkAndCreateRootDir() {
        File file = new File(mRootPath);
        if (!file.isFile() && file.exists()) {
            return;
        } else if (!file.exists()) {
            file.mkdirs();
        } else if (file.isFile()) {
            file.delete();
            file.mkdirs();
        }
    }

    private double lastbili = -1;

    private void receiveFile(DataInputStream inputStream, String data) throws IOException {
        DataOutputStream outputStream = null;
        try {
            long length = inputStream.readLong();
            String url = Protocol.realURL(data);
            String path = mRootPath + "/" + DirUtils.getFilePath(url);
            DirUtils.checkDirExist(path);
            File outFile = new File(path + "/" + DirUtils.getFileName(url));
            Log.d(TAG, "recive file:" + url + " save to" + outFile.getAbsolutePath());
            outFile.createNewFile();
            try {
            outputStream = new DataOutputStream(new BufferedOutputStream(
                    new FileOutputStream(outFile)));
            } catch (IOException exception) {
                Log.e(TAG, "file:" + outFile.getAbsolutePath() + " can not access, ingor it");
                //TODO do like this will not shengxiao
//                inputStream.skip(length);
//                return;
            }
            int bufferSize = RECEIVE_FILE_BUFFERE_SIZE;
            byte[] buf = new byte[bufferSize];
            long passedlen = 0;
            while (true && length > 0) {
                int read = 0;
                if (passedlen + bufferSize > length) {
                    buf = new byte[(int) (length - passedlen)];
                }
                read = inputStream.read(buf);
                passedlen += read;
                if (outputStream != null)
                    outputStream.write(buf, 0, read);
                double bili = passedlen * 100 / length;
                if (mFileTransferListener != null && lastbili != bili) {
                    mFileTransferListener.onProgressChanged(outFile.getAbsolutePath(), (int) bili);
                    lastbili = bili;
                }
                if (read == -1 || passedlen >= length)
                    break;
            }
            if (outputStream != null)
                outputStream.flush();
        } finally {
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }

    @Override
    public void run() {
        DataInputStream inputStream = null;
        try {
            inputStream = new DataInputStream(new BufferedInputStream(mInputStream));
            while (inputStream.readInt() != -1) {
                String data = inputStream.readUTF();
                Log.d(TAG, "Receive message :" + data);
                if (Protocol.sendFile(data)) {
                    receiveFile(inputStream, data);
                } else if (Protocol.sendMessage(data)) {
                    data = Protocol.realData(data);
                    if (mMessageListener != null) {
                        mMessageListener.receiveMessage(data);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
            if (mSocketErrorListener != null) {
                mSocketErrorListener.onSocketError(e);
            }
        }
    }

    public void release() {
        if (mInputStream != null) {
            try {
                mInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // For receiver need not to close the connection , connection will be
        // close by sender.
        // try {
        // mConnectionManager.release();
        // } catch (IOException e) {
        // e.printStackTrace();
        // }
    }
}
